python高阶爬虫实战分析
作者:芙兰Flan
关于这篇文章有几句话想说,首先给大家道歉,之前学的时候真的觉得下述的是比较厉害的东西,但是后来发现真的是基础中的基础,内容还不是很完全。再看一遍自己写的这篇文章,突然有种想自杀的冲动。emmm所以楼主决定本文全文抹掉重写一遍,并且为之前点进来看的七十多访问量的人,致以最诚挚的歉意。好想死。。
在学完了爬虫全部内容后,楼主觉得勉强有资格为接触爬虫的新人指指路了。那么废话不多说,以下正文:
一、获取内容
说爬虫一定要先说爬取内容的方法,python有这么几个支持爬虫的库,一个是urllib和它的后续版本库,这个库做爬取的时候生成的中继对象是比较多的,楼主也记不大住都有什么,而且这个库的使用在楼主看来有些过时了。更加建议做爬取的时候使用requests库(ps:不是request)
使用urllib:
html = urllib.request.urlopen(url).read()
使用requests:
r = requests.get(url)
对于获取到的内容,有以下方法进行处理:
1、使用正则表达式匹配。
2、使用BeautifulSoup对爬取内容标签对象化。
3、通过构造节点树使用Xpath获取元素。
第一种方法胜在直接,效率高而且不需要安装三方库。第二种方法胜在简单,标签对象化后不需要写复杂的正则表达式,而且提取标签更加方便。第三种方法胜在灵活,获取内容更加灵活,就是语法有点多,不熟的话可以对着Xpath语法文档写。
使用正则表达式匹配:
pattern_content = '<div class="rich_media_content " id="js_content">(.*?)</div>' content1 = re.findall(pattern_content, html, re.S)
使用BeautifulSoup对爬取内容标签对象化:
soup = bs4.BeautifulSoup(html, 'lxml') imgs = soup.find_all('img')
关于BeautifulSoup的安装请自行百度,没记错的话直接pip是可行的。
通过构造节点树使用Xpath获取元素:
selector=etree.HTML(html) content=selector.xpath('//div[@id="content"]/ul[@id="ul"]/li/text()')
至此,爬取的基本内容就叙述完毕了,这里给出的是最简单的范例,如果想深入了解某种方法,建议去查询更详细的技术文档。
下面内容就是之前的了,略作删改。
二、伪造表单请求头
很多网站上的数据爬取比较简单,只需要直接request那个网址就可以,很多小型网站都是这样。面对这样的网站数据,只需要花个几分钟随便写几行代码,就能爬到我们想要的数据。
但是想要爬取稍微大型一些的网站数据,就不会这么容易了。这些网站的服务器,会分析收到的每一条request,来判断该请求是否为用户操作。这种技术,我们把它称为反爬技术。常见的反爬技术,楼主知道的有上面所述的分析请求,还有验证码技术。对于这两种情况,我们在构造爬虫程序的时候就需要稍微费点力气了。
先来介绍第一种的应对方法。首先我们要知道一条request的组成部分,不同网站的request格式可能会有点不同。对于这一点,我们可以通过浏览器的开发者工具,抓到一个网站的请求数据格式。如下图:
11111
此为使用谷歌浏览器抓取的请求信息。
我们可以看到request headers的格式,所以在访问这样的网站的时候,我们就不能忘了在postdata中放上一条伪造的headers。
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:32.0) Gecko/20100101 Firefox/32.0', 'Referer': 'Address'}
其中referer键对应的值是要访问的网址。
某些网站还会需要有cookie的用户验证,我们可以通过调用
requests.Session().cookies
来获得它。
如果在爬虫中需要提交某些信息的话,还要构造一下postdata的数据。比如这样:
postData = { 'username': ul[i][0], 'password': ul[i][1], 'lt': b.group(1), 'execution': 'e1s1', '_eventId': 'submit', 'submit': '%B5%C7%C2%BC', }
三、关于多网页的爬取
如果网页地址有规律,那么构造url用个循环函数就好,对于网页地址中包含随机码的时候,通常就是先爬取根页面,获取到所有想爬取的子页面url,把这些url放进一个url池(项目小是一维的列表,项目大的时候可能会是高维的列表)里,循环爬取。
而比较高效的方式是使用多线程技术,demo有点长只贴关键部分。
class Geturl(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): res = requests.get(url, headers=header) html = res.text # print(html) pattern_href = '<a target="_blank" href="(.*?)" rel="external nofollow" id' href = re.findall(pattern_href, html, re.S) for href in href: href = href.replace('amp;', '') a.put(href) a.task_done() class Spider(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): href = a.get() res = requests.get(href, headers=header2) html = res.text pattern_title = '<title>(.*?)</title>' title = re.findall(pattern_title, html, re.S) pattern_content = '<div class="rich_media_content " id="js_content">(.*?)</div>' content1 = re.findall(pattern_content, html, re.S) print(title) # time.sleep(1.5) pattern_content2 = '>(.*?)<' content2 = re.findall(pattern_content2, content1[0], re.S) while '' in content2: content2.remove('') content = '' for i in content2: content = content + i content = content.replace(' ','') print(content)
开两个线程,一个爬取url放进url池,一个从url池里获取url然后爬取内容,再开一个线程监控两个线程,如果两个线程运行完毕,结束主线程。
python的多线程机制底层做的其实不好,理由不多讲。另,多线程具体操作很多就不展开讲了。
四、关于使用代理ip
很多网站会有ip检测机制,当同一ip以人力无法做到的速度多次访问网站时,通常就会触发这种机制。
代理ip的话,通常通过爬取一些开源ip网站发布的ip构建ip代理池,比如西刺、蘑菇等。这样的一些网站,直接百度代理ip就能找到。然后,使用Flask+Redis维护代理池。这部分详细说明也比较长,就不细说了。也不是爬虫必要的东西。另,自己有服务器的也可以使用SSR的翻墙工具,不过搭建不是楼主亲手做的,所以就不详细说明了。
五、关于selenium模仿浏览器操作
关于selenium主要介绍以下几点:
1、selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。
2、Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。
3、selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。
4、用python写爬虫的时候,主要用的是selenium的Webdriver。
这些是某说明文档的内容,能看懂就看,看不懂就看楼主的简单版:
selenium的话主要用于模仿浏览器操作,比如向文本框中赋值,点击按钮等。配合高效率浏览器的话也是实现爬虫的一个比较好的方法。优点是通过模拟浏览器操作,不易被反爬检测。缺点是效率低下,非常不适合大型爬虫,小作坊自己玩玩就好。
六、关于Scrapy框架
这又是一块非常非常庞大的内容,很多技术一旦牵扯上框架就麻烦了。当然学会了的话,做大型项目就简单多了。重点就是框架一般针对比较大型的系统去做,所以其管理和操作会比较麻烦,内部的一些机制也不是很好说明。这一块的话如果以后有时间就单独写一篇文章详细介绍,毕竟从原理到搭建到配置到使用,内容太多。。
七、关于验证码处理
对于处理验证码的话,目前简单点的是直接使用PIL(pillow)做图像处理,然后使用Tesseract直接识别。此方法楼主已经写好了单独的文章供大家参考。
另,如果学过机器学习神经网络这部分的话,还可以使用卷积神经网络。这个方向楼主还正在学,简单给大家指条路,不详述。
以上是楼主想到的爬虫所有内容,若有错误还望指正。