我们是谁?
萌新!
我们要什么?
学习爬虫!
什么时候要?
天天要!
其实一个爬虫无非就三步:下载数据、解析数据、保存数
本文提供一个代码示例,分别展示这三步骤
1
下载数据
def dowmlpad(url, user_agent='wswp', proxy=None, num_retries=2, timeout=5):
"""
# 支持500错误重试
# 设定用户代理 user_agent
# 支持ip代理
"""
print('DownloadURL:',url)
#配置用户代理
headers = {'User-agent':user_agent}
request = urllib.request.Request(url, headers=headers)
#配置
opener = urllib.request.build_opener()
#判断是否代理
if proxy:
proxy_params = {urllib.parse.urlparse(url).scheme:proxy}
opener.add_handler(urllib.request.ProxyHandler(proxy_params))
try:
html = opener.open(request, timeout=timeout).read()
except urllib.request.URLError as e:
print('Download error:',e.reason)
html = None
if num_retries > 0:
if hasattr(e,'code') and 500 <= e.code <600:
html = dowmlpad(url, user_agent, num_retries-1)
except Exception as e:
print('error :',e)
html = None
return html
2
解析数据
#编写爬取规则,获得数据
def scrape_callback(url,html):
csslist = ['span[property = "v:itemreviewed"]', 'span.year', 'strong[property="v:average"]']
try:
tree = lxml.html.fromstring(html)
row = [tree.cssselect('{0}'.format(field))[0].text for field in csslist]
print(url, row)
except Exception as e:
print("ScrapeCallback error:",e)
"""
seed_url:种子url
link_regex: 提取链接的正则表达式
max_depath:提取链接的深度,默认为2爬虫到达第二场页面后不再提取链接 ,对于种子页面取出的链接页面,就是第二层,
scrape_callback:回掉函数
"""
def link_crawler(seed_url, link_regex, max_depath=2, scrape_callback=None):
crawl_queue = [seed_url] #配置爬取队列,其实就是一个存储url的列表
#seen = set(crawl_queue)
seens = {seed_url:1}
# 循环直到队列为空退出
while crawl_queue:
url = crawl_queue.pop() # 移除队列最后一个元素,并返回值
html = dowmlpad(url) # 根据url 下载页面
depth = seens[url] # 获得url深度
print(depth) #获取页面中的链接
for link in get_links(html):
if depth != max_depath and re.search(link_regex,link):
link = urllib.parse.urljoin(seed_url, link) #组装规范链接
#添加链接到爬取队列中
if link not in seens:
seens[link] = depth+1
crawl_queue.append(link) #如果处理回调函数存在,则进行回调处理
if scrape_callback:
scrape_callback(url, html)
3
保存数据
import csvclass ScrapeCallback:
def __init__(self):
self.writer = csv.writer(open('countries.csv','w'))
self.fields = ('name','year','score')
self.writer.writerow(self.fields)
def __call__(self, url,html):
csslist = ['span[property = "v:itemreviewed"]', 'span.year','strong[property="v:average"]']
try:
tree = lxml.html.fromstring(html)
row = [tree.cssselect('{0}'.format(field))[0].text for field in csslist]
self.writer.writerow(row)
print(url, row)
except Exception as e:\
print("ScrapeCallback error:",e)
最后主函数
if __name__ == '__main__': #测试
send_url = "https://movie.douban.com/"
link_regex = '(/subject/[\d]+/)' #获取链接的规则
#使用类的方式来写,下面两个一样结果
link_crawler(send_url,link_regex,max_depath=2, scrape_callback=ScrapeCallback())
#link_crawler(send_url, link_regex, max_depath=2, scrape_callback=scrape_callback)
这里只是大致展示了框架,更详细的注释可以去zhangslob/Python-General-Spider
爬虫其实很简单,不要过于纠结方法,记住三步:下载数据、解析数据、保存数据
本文分享自 Python爬虫与算法进阶 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!