WSWP(用python写爬虫)笔记二:实现链接获取和数据存储爬虫

来源:互联网 发布:与美食有关的句子 知乎 编辑:程序博客网 时间:2024/05/16 17:27

前面已经构建了一个获取链接的爬虫模块,现在继续完善这个爬虫。

分析网页

要对一个网页中的数据进行提取,需要先对网页的结构有一个大体的了解,通过在浏览器查看网页源代码的方法就能实现。
在了解到网页的结构后,接下来便是获取自己想要的数据了,个人比较喜欢用Chrome浏览器的检查元素的方式来定位数据在html源码中的位置(根据个人喜好来选择,不过建议直接使用chrome自带的,后面获取解析内容的css selector或XPath比较方便)。例如,我想要爬取某篇blog的内容,直接在Chrome中打开blog的url,并在感兴趣的内容上依次点击右键 -> 检查便能定位到数据在网页源码中的位置。如图所示:
oops
结果如下:
oops

如此便得到了想要爬取的内容存在于标签< div class=”markdown_views”>之中。
接下来便是通过解析网页获取到目标内容并进行抓取了。

数据抓取

测试url: http://example.webscraping.com/places/default/view/China-47
抓取的数据: 国土面积
oops
数据在网页源码中的位置:
oops
可以看出所想抓取的数据的位置在< td class=”w2p_fw”>中。
接下来介绍三种抓取数据的方式,首先是经典的正则表达式匹配法,然后是python中比较流行的Beautifulsoup模块,最后是强大的lxml模块。

正则表达式

对于正则表达式不清楚的,可以先阅读 正则表达式。
通过正则表达式抓取面积数据时,首先尝试匹配< td class=”w2p_fw”>中的内容,示例如下:

# re_test.pyfrom wswp_1_pro.downloader import downloadimport reurl = 'http://example.webscraping.com/places/default/view/China-47'html = download(url, headers={'User-agent':'wswp'}, proxy=None, numRetries=2)for content in re.findall('<td class="w2p_fw">(.*?)</td>', str(html)):    print(content)

结果如下:
oops
从上面的结果中可以看出,解析出了很多内容,返回到源码中可以看出多个属性都使用了< td class=”w2p_fw”>标签。如果想要分离出面积属性,可以只选择其中的第二个元素即可。

# re_test.pyfrom wswp_1_pro.downloader import downloadimport reurl = 'http://example.webscraping.com/places/default/view/China-47'html = download(url, headers={'User-agent':'wswp'}, proxy=None, numRetries=2)# for content in re.findall('<td class="w2p_fw">(.*?)</td>', str(html)):#     print(content)area = re.findall('<td class="w2p_fw">(.*?)</td>', str(html))[1]print("面积为:", area)

结果如下:
这里写图片描述
使用正则表达式的缺点是不够灵活,如果网页的将属性值更改以后,则需要重新更改正则表达式。

BeautifulSoup模块

BeautifulSoup在网页数据解析时非常强大,提供定位内容的便捷接口。
首先通过pip安全该模块。

pip install bs4

使用BeautifulSoup的第一步是将已经下载好的html内容解析为soup文档(对网页内容进行正确解析并对未闭合的标签进行闭合)。然后可以使用find()和findall()来定位所需要的元素了。
以下是使用BeautifuSoup提取示例国家面积数据的完整代码:

from bs4 import BeautifulSoupfrom wswp_1_pro.downloader import downloadurl = 'http://example.webscraping.com/places/default/view/China-47'html = download(url, headers={'User-agent':'wswp'}, proxy=None, numRetries=2)soup = BeautifulSoup(html, "html.parser")# 先定位面积的父标签tr = soup.find(attrs={'id':'places_area__row'})# 通过父标签再来定位子标签td = tr.find(attrs={'class':'w2p_fw'})area = td.textprint("面积为:", area)
lxml模块

lxml官网点击这里^_^。
lxml pdf文档下载。
lxml通过pip安装。

pip install lxml

lxml模块跟BeautifulSoup一样,将下载的html解析为统一格式(修复不闭合的标签)。示例代码如下:

from wswp_1_pro.downloader import downloadimport lxml.htmlurl = 'http://example.webscraping.com/places/default/view/China-47'html = download(url, headers={'User-agent':'wswp'}, proxy=None, numRetries=2)tree = lxml.html.fromstring(str(html))# 从面积的父标签开始提取内容td = tree.cssselect('tr#places_area__row > td.w2p_fw')[0]area = td.text_content()print("面积为:", area)

上述代码中使用cssselect(CSS选择器)可通过pip直接安装。
lxml有几种不同的方法进行元素的选择,比如XPath选择器、CSS选择器和类似于BeautifulSoup中的find方法。选用CSS选择器,因为其更加简洁,并且在能够解析动态内容。(可通过Chrome中选择检查元素,copy –> Copy selector来直接从浏览器中获取到CSS选择器的参数,然后再根据实际情况进行精简处理),CSS选择器的参考教程请点这里。

使用XPath选择器的代码如下:

from wswp_1_pro.downloader import downloadimport lxml.htmlurl = 'http://example.webscraping.com/places/default/view/China-47'html = download(url, headers={'User-agent':'wswp'}, proxy=None, numRetries=2)tree = lxml.html.fromstring(str(html))# 从面积的父标签开始提取内容td = tree.xpath('//tr[@id="places_area__row"]/td[@class="w2p_fw"]')[0]area = td.text_content()print("面积为:", area)

以上就是从网页中获取感兴趣的数据的方法,接下来就是向爬虫程序中添加针对爬取到的数据的处理方法了。

为链接爬虫添加抓取回调

前面实现的链接爬虫如果想要复用到抓取其他网站的数据,需要添加一个callback参数参与抓取行为。callback是一个函数,在发生某个特定事件之后会调用该函数(在本例中会在网页下载完成后调用)。
实现的callback函数包含url和html两个参数,并且可以反回一个待爬取的url列表。在linkCrawler.py中添加代码,如下所示:

# linkCrawler.pydef linkCrawler(..., scrapeCallBack=None):    ...    links = []    if scrapeCallBack:        links.extend(scrapeCallBack(url, html) or [])        ...

现在只需要对传入的callback函数进行定制化处理,就能使用该爬虫对其他网站进行爬取了。下面对使用lxml抓取国土面积的代码进行修改,使其能在callback中使用。

import reimport lxml.htmlfrom wswp_1_pro.linkCrawler import linkCrawlerFIELDS = ['area', 'population', 'iso', 'capital', 'continent', 'tld', 'currency_code', 'currency_name', 'phone', 'postal_code_format', 'postal_code_regex', 'languages', 'neighbours']def scrapeCallBack(url, html):    if re.search('/view/', url):        tree = lxml.html.fromstring(str(html))        row = [tree.cssselect('table > tr#places_%s__row > td.w2p_fw' % field)[0].text_content() for field in FIELDS]        for text, content in zip(FIELDS,row):            print(text + ' : ' + content)if __name__ == "__main__":    linkCrawler('http://example.webscraping.com/', '.*?/(index|view)', maxDepth=2, scrapeCallBack=scrapeCallBack)

结果如下:
oops

上一个callback函数会去抓取国家数据,然后显示出来。通常情况下,在抓取网站时,更希望能够复用这些数据,下面对callback的功能进行扩展,将得到的结果数据保存到CSV表格中,代码如下:

# callBack_test.pyimport csvimport reimport lxml.htmlfrom wswp_1_pro.linkCrawler import linkCrawlerclass ScrapeCallback:    def __init__(self):        self.writer = csv.writer(open('countries.csv', 'w'))        self.fields = ('area', 'population', 'iso', 'country', 'capital', 'continent', 'tld', 'currency_code', 'currency_name', 'phone', 'postal_code_format', 'postal_code_regex', 'languages', 'neighbours')        self.writer.writerow(self.fields)    def __call__(self, url, html):        if re.search('/view/', url):            tree = lxml.html.fromstring(html)            row = []            for field in self.fields:                row.append(tree.cssselect('table > tr#places_{}__row > td.w2p_fw'.format(field))[0].text_content())            self.writer.writerow(row)if __name__ == '__main__':    linkCrawler('http://example.webscraping.com/', '/(index|view)', maxDepth=3, scrapeCallBack=ScrapeCallback())

结果如下:
oops

上面的callback,使用了回调类,而不再是回调函数,以便保持csv中writer的属性状态。csv的writer属性在构造方法中进行了实例化处理,然后在 __call__ 方法中执行多次写操作。__call__()是一个特殊的方法,在对象作为函数被调用是会调用该方法。

成功了,完成了一个可以工作的数据获取爬虫了。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝卖家认证无法通过怎么办 淘宝开店申请未认证该怎么办 传照片到淘宝看不到照片怎么办 淘宝店铺秒出复核怎么办 钱盾身份认证一直不通过怎么办 淘宝开店一直不让认证通过怎么办 淘宝店铺不卖东西怎么办 企业误进虚空的增值税发票怎么办 唯品会商品有的不支持退换货怎么办 苹果手机和平板电脑共享怎么办 ipad被锁定了停用了怎么办 word文档被锁定不能编辑怎么办 苹果平板id忘了怎么办 ipad有id锁怎么办换主板 ipad刷机后忘记id密码怎么办 网购买东西手机号错了怎么办? 淘宝卖家虚假交易违规怎么办 好朋友问我借身份证开网店怎么办 为什么淘宝点开就跳过打不开怎么办 刹车油进眼睛里怎么办 眼睛被uv灯刺伤怎么办 眼睛被uv灯伤了怎么办 洗手台靠不到墙怎么办 加盟天猫优品不想干了怎么办 口袋侦探点开始就闪退怎么办 淘宝号被监控了怎么办 excel表格中把字体变细怎么办 wps方框中打字打不上怎么办 蘑菇街里面买东西受骗了怎么办? 淘宝买家号账户体检中心违规怎么办 支付宝充错手机账号怎么办 美团恶意差评怎么办 买家好评后追加差评怎么办 宝贝吃了一个金币怎么办 店铺微淘等级l1怎么办 淘宝占内存2个g怎么办 淘宝太占空间了怎么办 支付宝占内存大怎么办 苹果手机储存空间不足怎么办 小米平板电脑储存空间不足怎么办 ipad2很卡反应慢怎么办