一、3种常见的爬取网站的方法
首先我们需要下载网站中需要的网页,通常下载网站的网页有如下3种方式:
- 爬取网站地图(sitemap)
- 遍历每个网页的数据库ID
- 跟踪网页链接
在python3中将python2中的urllib和urllib2合并为urllib。
1. 爬取网站地图(sitemap)
适用情况:所爬取的网站中有网站地图(sitemap)。
适用正则表达式或是CSS选择器从sitemap中抽取出url,爬取这些url。
优点:简单便捷。
缺点:无法通过sitemap获取到每个网页的链接,而且可能有的网站没有sitemap,无法保证这种方法始终可用。
2. 遍历每个网页的数据库ID
适用情况:能够找到网站url的结构和规律。
分析该网站下的url的规律,根据这些规律构建出url,爬取这些url。
优点:便捷。
缺点:无法保证始终可用,有的网站的url规律较为复杂,使用ID来遍历爬取url效率太低。
3. 跟踪网页链接(常用)
其实现在,使用的user_agent可以用python3的一个包,叫作Fake-useragent,很方便。
适用情况:贼拉广。
优点:能够下载整个网站的页面。
缺点:会下载大量我们并不需要的网页。
import re
import urllib
from urllib import parse
def link_crawl(seed_url, link_regex, max_depth=1):
"""
:param seed_url: 种子url,爬取的原始url
:param link_regex: 匹配url的正则表达式
:param max_depth: 爬虫的最大深度,例如父页面深度为1,其子页面为2,子页面的子为3,依次类推
"""
# 一个列表保存需要爬取的url,可以理解成一个队列
crawl_queue = [seed_url]
# 保存已经加入待爬取队列的url
seen = {}
while crawl_queue:
url = crawl_queue.pop()
# 这个url代表的网页的深度
depth = seen[url]
if depth <= max_depth:
html = download(url)
for link in get_links(html):
# 相对链接=>绝对链接
link = parse.urljoin(seed_url, link)
if link not in seen:
seen[link] = depth + 1
crawl_queue.append(link)
def download(url, user_agent='wswp', proxy=None, num_retries=2):
"""
:param url: 待下载的url
:param user_agent: 用户代理,表明用户以什么方式来访问的这个url
:param proxy: 代理
:param num_retries: 重试次数,下载失败超过这个次数则不在下载此url
"""
print('Downloading: {}'.format(url))
headers = {'User-Agent': user_agent}
request = urllib.request.Request(url, headers=headers)
opener = urllib.request.build_opener()
if proxy:
proxy_params = {parse.urlparse(url}.scheme: proxy}
opener.add_handler(urllib.request.ProxyHandler(proxy_params))
try:
html = opener.open(request).read()
except urllib.error.URLError as e:
print('Download error: {}'.format(e.reason))
html = None
if num_retries > 0:
# 返回状态码是5xx则重试
if hasattr(e, 'code') and 500 <- e.code < 600:
html = download(url, user_agent, proxy, num_retries-1)
return html
def get_links(html):
"""
从html返回url列表
"""
webpage_regex = re.compile('<a[^>]+href=["\'](.*?)["\']', re.IGNORECASE)
return webpage_regex.findall(html)
二、3中抽取网页数据的方法
在获取到了指定网页的html数据之后,我们需要从html中抽取出需要的数据,扔掉无用的数据。这个过程叫作抓取(scraping)。
- 正则表达式
优点:抽取性能快。
缺点:使用难度较大,而且正则表达式来抽取网页数据这种方法比较脆弱,若网页结构发生改变,容易失效。
- Beautiful Soup
优点:更健壮,即使网页结构发生改变,仍然能够有效使用。
缺点:抽取性能慢。
- lxml
优点:抽取性能快。
缺点:使用较Beautiful Soup复杂,但是较正则表达式简单。
通常情况下,lxml是抓取数据的最好选择,这是因为该方法既快又健壮,而正则表达式和Beautiful Soup只能在某些特定场景下有用。