package main
import (
"fmt"
"log"
"net/http"
"os"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
// 初始化日志配置
func initLogger() (*zap.Logger, error) {
encoderConfig := zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochMillisTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
}
core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), os.Stdout, zapcore.InfoLevel)
return zap.New(core), nil
}
// 解析HTML并提取指定的元素
func extractElements(doc *html.Node, targetAtom atom.Atom) []*html.Node {
var elements []*html.Node
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.DataAtom == targetAtom {
elements = append(elements, n)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
return elements
}
// 爬取指定URL的页面内容
func crawlPage(logger *zap.Logger, url string) (string, error) {
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Get(url)
if err != nil {
logger.Error("Error fetching URL", zap.Error(err), zap.String("url", url))
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
logger.Error("Received non-200 HTTP status code", zap.Int("status_code", resp.StatusCode), zap.String("url", url))
return "", fmt.Errorf("non-200 status code: %d", resp.StatusCode)
}
doc, err := html.Parse(resp.Body)
if err != nil {
logger.Error("Error parsing HTML", zap.Error(err), zap.String("url", url))
return "", err
}
// 假设我们要提取所有的h1元素
h1Elements := extractElements(doc, atom.H1)
var content string
for _, elem := range h1Elements {
for _, n := range elem.ChildNodes {
content += n.Data
}
}
return content, nil
}
func main() {
logger, err := initLogger()
if err != nil {
log.Fatalf("Error initializing logger: %v", err)
}
defer logger.Sync()
content, err := crawlPage(logger, "https://example.com")
if err != nil {
logger.Error("Crawling failed", zap.E
package main
import (
"fmt"
"log"
"net/http"
"os"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/net/html"
)
// 初始化日志配置
func initLogger() (*zap.Logger, error) {
encoderConfig := zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochMillisTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
}
core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), os.Stdout, zapcore.InfoLevel)
return zap.New(core), nil
}
// 爬取指定URL的所有链接
func crawl(logger *zap.Logger, url string) ([]string, error) {
resp, err := http.Get(url)
if err != nil {
logger.Error("Error fetching URL", zap.Error(err), zap.String("url", url))
return nil, err
}
defer resp.Body.Close()
doc, err := html.Parse(resp.Body)
if err != nil {
logger.Error("Error parsing HTML", zap.Error(err), zap.String("url", url))
return nil, err
}
var links []string
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a" {
for _, a := range n.Attr {
if a.Key != "href" {
continue
}
link := a.Val
if link != "" && !strings.HasPrefix(link, "http") {
links = append(links, link)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
return links, nil
}
func main() {
logger, err := initLogger()
if err != nil {
log.Fatalf("Error initializing logger: %v", err)
}
defer logger.Sync()
start := time.Now()
siteURL := "https://example.com"
links, err := crawl(logger, siteURL)
if err != nil {
logger.Error("Crawl failed", zap.Error(err), zap.String("siteURL", siteURL))
return
}
logger.Info("Crawl successful",
zap.Int("num_links", len(links)),
zap.String("siteURL", siteURL),
zap.Duration("took", time.Since(start)),
)
for _, link := range links {
fmt.Println(link)
}
}
这段代码使用了Uber的Zap日志库来替换标准库的log,并使用了一个简单的HTML解析函数来抓取指定URL页面上的所有链接。代码示例中的crawl
函数实现了爬取逻辑,并且使用了一个递归函数来遍历HTML文档树。这个例子教导了如何使用Go语言进行基本的网络爬虫编写,并且展示了如何使用Zap日志库记录有意义的
问题解释:
使用Selenium打开浏览器后,浏览器会自动关闭。这通常是因为Selenium驱动的浏览器执行完成后,驱动程序调用了关闭浏览器的操作。
解决方法:
- 检查你的Selenium脚本,确保没有在脚本的最后调用关闭浏览器的命令。如果有,请移除或注释掉这些命令。
- 如果你是在循环中使用Selenium打开多个浏览器窗口,确保每个窗口都是独立打开和管理的,而不是共享同一个WebDriver实例。
- 确保浏览器驱动版本与浏览器版本兼容,并且正确安装。
- 如果使用的是headless模式(无界面模式),确保浏览器配置支持headless模式。
- 检查是否有其他外部因素(如定时任务、异常处理等)导致浏览器被关闭。
示例代码(Python):
from selenium import webdriver
# 确保移除或注释掉关闭浏览器的命令
# driver.quit() # 注释掉或移除这行
# 其他操作代码
# 最后保存并退出
如果以上方法都不能解决问题,可能需要更详细地调查代码逻辑或查看具体的错误信息,以确定问题的根源。
由于原始代码已经提供了一个很好的示例,以下是一个简化的核心函数,演示如何使用Python和requests库来发送请求,并使用BeautifulSoup库来解析HTML,以便提取信息。
import requests
from bs4 import BeautifulSoup
def get_job_info(url):
# 发送请求
response = requests.get(url)
response.raise_for_status() # 检查请求是否成功
soup = BeautifulSoup(response.text, 'html.parser') # 解析HTML内容
# 提取职位信息
job_info = {
'title': soup.select_one('.job-name').text.strip(),
'salary': soup.select_one('.job-salary').text.strip(),
'company': soup.select_one('.company-name').text.strip(),
'city': soup.select_one('.job-addr').text.strip(),
'description': soup.select_one('.job-detail').text.strip()
}
return job_info
# 使用函数
url = 'https://www.liepin.com/job/123456.html' # 假设的职位URL
info = get_job_info(url)
print(info)
这个简化的代码演示了如何使用requests库获取网页内容,并使用BeautifulSoup进行HTML内容的解析。代码中的soup.select_one()
方法使用CSS选择器来定位页面元素,并通过.text.strip()
获取元素的文本内容。这个例子教会开发者如何利用Python进行简单的网页爬取。
import requests
from pyquery import PyQuery as pq
import pandas as pd
# 请求拼多多商品列表页面
def get_items(url):
headers = {
'User-Agent': 'your_user_agent',
'Referer': 'https://www.pinduoduo.com/',
}
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
except requests.RequestException:
return None
# 解析商品信息
def parse_items(html):
doc = pq(html)
items = doc('.goods-list .goods-item').items()
for item in items:
yield {
'image': item('.goods-img').attr('src'),
'price': item('.price').text(),
'deal_num': item('.deal-cnt').text(),
'shop_name': item('.shop-name').text(),
'item_url': item('.goods-img').attr('href'),
}
# 保存商品信息到CSV文件
def save_to_csv(items, filepath):
df = pd.DataFrame(items)
df.to_csv(filepath, index=False, encoding='utf-8-sig')
# 主函数
def main(url, filepath):
html = get_items(url)
items = parse_items(html)
save_to_csv(items, filepath)
if __name__ == '__main__':
url = 'https://www.pinduoduo.com/commodity_list/some_category_id'
filepath = 'items.csv'
main(url, filepath)
这个示例代码展示了如何使用Python进行简单的网页爬取,并将爬取的数据保存到CSV文件中。代码中使用了requests库来发送HTTP请求,使用pyquery库来解析HTML页面,并使用pandas库来处理和保存数据。需要注意的是,这个例子只是一个简单的教学示例,实际的爬虫项目可能需要更复杂的处理,比如处理登录验证、分页请求、用户代理随机化、反爬机制应对等。
在Python中,你可以使用requests
库来发送HTTP请求,并获取返回的响应头信息。以下是一个示例代码,展示了如何获取请求头中的User-Agent
和Cookie
信息:
import requests
url = 'http://example.com' # 替换为你想爬取的网站
# 发送HTTP请求
response = requests.get(url)
# 获取User-Agent
user_agent = response.request.headers.get('User-Agent')
print('User-Agent:', user_agent)
# 获取Cookie
cookies = response.cookies
for cookie in cookies:
print(cookie.name, ':', cookie.value)
确保在使用这段代码前已经安装了requests
库,可以使用pip install requests
来安装。
此代码发送一个GET请求到指定的URL,然后打印出响应中的User-Agent
和所有Cookie
信息。response.request.headers
包含了发送请求时的HTTP头部信息,而response.cookies
是一个包含服务器设置的Cookie的容器。
from pyquery import PyQuery as pq
# 示例HTML字符串
html = '''
<div id="container">
<ul class="list">
<li class="item-0">first item</li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-0"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
</ul>
</div>
'''
# 使用pyquery解析HTML字符串
doc = pq(html)
# 提取所有的li标签中的文本内容
items = [item.text() for item in doc('.list .item-0').items()]
print(items) # 输出: ['first item', 'third item']
# 提取所有的a标签的href属性
links = [link.attr('href') for link in doc('.list .item-1 a').items()]
print(links) # 输出: ['link2.html', 'link4.html']
这个代码实例展示了如何使用pyquery库来解析HTML字符串,并提取特定元素的文本内容或属性。代码首先定义了一个HTML字符串,然后使用pyquery的pq()
函数进行解析。接下来,使用CSS选择器来定位特定的元素,并通过.items()
方法迭代这些元素,最后使用.text()
或.attr()
方法来提取文本内容或属性。
import requests
from lxml import etree
import csv
import time
# 设置请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
}
# 设置CSV文件头
csv_headers = ['商品名称', '商品价格', '商品评分', '销售商信息', '商品链接']
# 设置代理服务器
proxy = {'http': 'http://120.77.138.138:80', 'https': 'https://120.77.138.138:80'}
# 设置请求超时时间
timeout = 10
# 设置请求失败的重试次数
max_retries = 5
# 初始化请求计数器
retries_count = 0
# 初始化CSV文件
with open('temu_data.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=csv_headers)
writer.writeheader()
# 设置爬取页数
for page in range(1, 11):
print(f'正在爬取第{page}页数据...')
url = f'https://www.temu.com/search/?q=%E6%B5%8B%E8%AF%95&sort=rank&page={page}'
# 实施重试机制
while retries_count < max_retries:
try:
response = requests.get(url, headers=headers, proxies=proxy, timeout=timeout)
response.raise_for_status() # 检查是否请求成功
retries_count = 0 # 重置请求计数器
break
except requests.exceptions.RequestException as e:
print(f'请求失败,原因:{e}')
retries_count += 1
time.sleep(5) # 等待5秒后重试
# 解析HTML内容
tree = etree.HTML(response.text)
product_items = tree.xpath('//div[@class="product-item"]')
for product_item in product_items:
name = product_item.xpath('.//h3/a/text()')[0].strip()
price = product_item.xpath('.//div[@class="product-price"]/span/text()')[0].strip()
score = product_item.xpath('.//div[@class="product-score"]/text()')[0].strip()
seller = product_item.xpath('.//div[@class="product-seller"]/text()')[0].strip()
link = product_item.xpath('.//h3/a/@href')[0].strip()
# 将数据写入CSV文件
writer.writerow({
'商品名称': name,
'商品价格': price,
'商品评分': score,
'销售商信息': seller,
'商品链接': link
})
print(f'第{page}页数据爬取完成。\n')
time.sleep(2) # 为了避免对服务器造成过大压力,设置2秒钟的间隔
print('所有页面数据爬取完成。')
这段代码使用了requests库来发送HTTP请求,并使用lxml库来解析HTML内容。同时,使用了CSV库来保存爬取的数据。代码中的重试机制能够处理网络请求失败的情况,并在请求失败时进行重试。最后,代码会在控制台输出爬取的状态信息,并在完成
以下是一个简化的、基于Python3的网络爬虫示例,用于从百度搜索结果中抓取特定关键词的网页。请注意,实际的网络爬虫可能需要遵守robots.txt协议,以及处理更复杂的情况,比如网页的动态加载、登录验证等。
import requests
from bs4 import BeautifulSoup
def crawl_web(keyword):
# 构造请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
# 搜索请求的URL
base_url = 'https://www.baidu.com/s?wd='
url = base_url + keyword
try:
# 发送GET请求
response = requests.get(url, headers=headers)
# 检查响应状态
if response.status_code == 200:
# 解析网页
soup = BeautifulSoup(response.text, 'html.parser')
# 提取搜索结果中的网页链接
links = soup.find_all('h3', class_='t')
for link in links:
print(link.a.get('href'))
else:
print('Failed to retrieve search results for:', keyword)
except requests.exceptions.RequestException as e:
print('Failed to crawl web. Error:', e)
# 使用关键词作为参数调用函数
crawl_web('Python')
这段代码使用了requests
库来发送HTTP请求,以及BeautifulSoup
库来解析HTML并提取数据。代码中的crawl_web
函数接收一个搜索关键词,构造请求URL,发送请求,并解析返回的HTML内容以提取搜索结果中的链接。
请注意,这个示例没有处理网页内容的详细解析,只是提取了搜索结果标题下的链接。实际的爬虫可能需要进一步提取有价值的数据,并可能需要处理网页中的AJAX、JavaScript渲染的内容。
urllib
库是Python内置的网络请求库,提供了几个模块用于处理URLs,包括urllib.request
用于打开和读取URLs,urllib.parse
用于解析URLs,以及urllib.error
用于处理请求过程中引发的异常。
以下是使用urllib.request
模块下载网页内容的示例代码:
import urllib.request
# 指定要下载的网页URL
url = 'http://www.example.com/'
# 使用urlopen方法打开并读取URL指定的网页内容
response = urllib.request.urlopen(url)
# 读取网页内容
html = response.read()
# 将网页内容转换为字符串
html_string = html.decode('utf-8')
# 打印网页内容
print(html_string)
以上代码演示了如何使用urllib.request
来打开和读取一个网页的内容,并把它转换为字符串。在实际应用中,你可能还需要处理HTTPS请求、POST数据、设置请求头部等更复杂的情况,但这个示例提供了基本的使用方法。