java爬虫代码示例_Python 爬虫进阶:从Requests到Scrapy 学习心得 *小说下载代码示例...

今天终于部署了第一个scrapy爬虫,内心感慨万千。上周一直沉浸于使用requests的简洁直观之中,对scrapy臃肿的体系非常头痛。把两周以来从零学起的小小心得陈列如下:

Requests 入门

我是学习莫烦的爬虫基础途中,突然就在python上开了窍。强烈推荐他的爬虫教程。

目前使用爬虫是为了下载没有全文阅读选项的小说,要把整本书的单个章节全部下载下来,合并成一个文档。

Requests的流程非常人性化:

  1. 先将网页的内容抓取下来
html 

2. 使用BeautifulSoup解析网页内容

soup = BeautifulSoup(html, features='html.parser')

3. 在soup里面用html的标签选择想要的内容,即小说某章节内容

work_contents = soup.find('div', {'id':'chapters'}).get_text(separator='n')

4. 到这一步爬虫功能已经完工。

5. 接下来是用普通的python语法将章节内容写到本地文件(这里保存为txt格式)

with open("chapter.txt, "w", encoding="utf-8") as f:
    f.writelines(work_contents)

6. 下载小说单章内容的代码已经全部完成!简单、轻松、快捷!

7. 那么,要下载多个章节怎么办呢?很简单,用for loop将上面的全部代码包裹起来,依次循环,每次更新一个章节的地址(url)以下载该章内容,同时更新文本文档名字(创建一个新文本)以写入该章内容。

pages = 12
for page in range(1, pages+1): # for loop
    # some updated code
    url = url + str(page) # sample code for updating url
    
    html = ...
    soup = ...
    work_contents = ...
   
    with open(f"{page}.txt","w", encoding="utf-8") as f: # sample code for updating file name
        f.writelines(work_contents)

    time.sleep(10) # delay the next round for 10 sec, avoid scraping too fast

8. 为了减缓爬取速度,避免被网站封禁,在抓取每个网页之间人工加上了延迟,即上面代码中的time.sleep()功能。

9. 至此,下载小说全本章节的代码也完工了!

Requests + Selenium 进阶

想爬取的网页需要登录,遇到这种情况又怎么办呢?有两种办法:

使用requests.Session.post()功能在请求网页时发送用户名和密码,可以保存coockies以保持登录状态;

或者,使用第三方神器Selemium+Katalon Recorder在firefox上模拟登录,并把cookies传送到requests.Session()中,达到登录目的。

稍微介绍一下第二种方式的流程:

  1. 在代码中首先载入Selenium driver,这里使用了Chrome浏览器来模拟。再将登录页面的url传入driver.get()。
driver = webdriver.Chrome()
driver.get(url)

2. 接着打开Firefox浏览器,开启Katalon Recorder的record(录制)功能。正常输入用户名、密码,点击登录按钮,等待页面跳转。(这一步在浏览器中操作)

3. 关闭Katalon Recorder录制,点击export(导出),复制类似下面代码到python中。

driver.find_element_by_xpath().click() # sample code
driver.find_element_by_xpath().send_keys(username)
driver.find_element_by_xpath().click()
driver.find_element_by_xpath().send_keys(password)

4. 这样就完成了Selenium登录的过程,接下来是将cookies传入requests.Session()中。

cookies = driver.get_cookies()
session = requests.Session()
for cookie in cookies:
    session.cookies.set(cookie['name'], cookie['value'])

5. 之后可以正常使用session.get()来请求网页,同时保持登录状态。

Scrapy 高级

熟练使用requests一周以后,我想要一次性爬取数百个网页。有几个困难,首先是当前的代码没有断点续传功能,另外为了避免网站封禁,总体等待时长已经达到了三个小时以上。

这个时候,已经封装了各种功能的Scrapy包就体现出了它的优势。看一下这个感天动地的回答吧——为啥要用scrapy代替requests或者urllib2:

  • 自动限速
  • 尊重网站的机器人条款
  • 处理网页有优势
  • 自动重试
  • 导出文件
  • 自动缓存

然而,比起requests线性的直观体验,scrapy的入门学习坡度更抖。这里有一篇非常完美的scrapy下载小说教程小白进阶之Scrapy第一篇。

操作scrapy的流程如下:

  1. 安装scrapy。我的上一篇文章涵盖了这一部分。
pip install scrapy

2. 在终端中使用 scrapy startproject 命令创建新的scrapy文件夹

scrapy startproject myspider

在项目文件夹中,scrapy已经自带了数个python文件,其中:

  • items - 负责保存网页内容
  • spiders - 负责抓取网页,在此目录下建一个新的python文件来写scrapy爬虫
  • pipelines - 负责导出文件到本地
  • settings - 控制爬虫速度、自动限速、以及其它附加功能
  • middlewares - 本地缓存等功能

由此可以看出,scrapy将requests的功能分开了,封装到不同的文件下,更加自动化。

3. 现在正式开始使用scrapy。首先,在Item中为想要抓取的内容命名。

class MySpiderItem(scrapy.Item):
    title = scrapy.Field() # sample code
    contents = scrapy.Field()
    pass

4. 接着,在spiders文件夹下创建一个新的python文件,例如myspider,py。在此处开始写爬虫。

首先为爬虫命名:

class MySpider(scrapy.Spider):
    name = "myspider"

接着,如果是由一个或数个网址开始往下爬,则写入start_urls(是一个列表[])。

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = ["url"]

假设我一共有5个网页要爬,每个网页又有数个链接,最终目标是抓取5个页面上的每个链接的内容。

我希望避免手写列表,而用for loop来组成起始网址(就像requests的做法一样)。那么,

page = 5
class MySpider(scrapy.Spider):
    name = "myspider"
    bash_url = url

    def start_requests(self):
        for i in (1, page+1):
            url = self.base_url + str(i)
            yield Request(url, self.parse)

这里,最后一行的yield会持续抛出Request()对当前url的解析内容(即response),然后用一个回调函数传入parse方法中。

我们接着来看parse方法。接着往下写。

    def parse(self, response):
        atags = BeautifulSoup(response.text, 'lxml').find_all('a', {'class':'name'})
        urls = [l['href'] for l in atags] 
        for url in urls:
            yield Request(url, callback=self.get_content)

现在,parse首先用BeautifulSoup分析了传过来的网页内容。先提取了页面上所有符合条件的<a href="url"></a>标签。接着用该语句提取标签内部的url。

urls = [l['href'] for l in atags] 

现在我们已经提取了单个页面上所有符合条件的url。针对每一个url,我们继续用yield抛出Request()对这些新的url的解析,其后传入下一个方法get_content()中,抓出新页面的内容。

下面是get_content()方法示例。

    def get_content(self, response):
        soup = BeautifulSoup(response.text, 'lxml')
        item = ScrapyTeaItem()
        item['title'] = soup.find('p', {'class':'family'}).get_text()
        item['contents'] = soup.find('p', {'class':'name'}).get_text()
        return item

看到这里,myspider.py终于和items.py联系上了。至此,爬虫已经爬完了五个网页上所有链接页面的内容,并将抓取的内容输入到items里面。

5. 现在,我们可以打开pipelines来存储items中的内容了。不过,要启用pipelines功能,我们得先打开settings.py文件,删除ITEM_PIPELINES = {前面的#号注释。

回到pipelines文件。将抓取的网页内容写入本地txt文件的代码如下。

class MySpiderPipeline(object):
    def process_item(self, item, spider):
        with open('myspider.txt', 'a', encoding='utf-8') as f: # "a" for append mode
            f.write('n'+ item['title'] + 'n') # one line
            f.writelines(item['contents']) # multiple lines
        return item

这样,保存网页内容的代码也写好了。

6. 如果想要控制爬取速度,则在settings中设置:

  • 要打开自动限速,则取消掉AUTOTHROTTLE前的#注释
  • 要人为限速,或者设置自动限速的最低值,取消DOWNLOAD_DELAY前的#注释

7. 现在开始运行我们所写的爬虫。在终端中输入 scrapy crawl myspider 即可运行,创建的txt文档会保存在此项目的根目录下。

至此,scrapy爬虫已经成功写好!

Scrapy Cloud

scrapy还提供云端爬虫服务,免费用户可以一次运行一个爬虫。

  1. 注册https://scrapinghub.com/scrapy-cloud

2. 点击CREATE PROJECT(创建项目),输入项目名称

3. 进入Deploy Management页面,这里介绍Command line使用终端将本地项目传到云端

4. 在本地项目文件夹的终端中(在终端中使用cd和cd...命令来前进或后退文件夹),运行代码。

 pip install shub

安装完全以后,再运行

shub login

在提示的API KEY处,输入云端页面上的API键

然后使用以下语句将本地项目推送到云端

shub deploy #加上云端页面上的id号码

如果使用BeautifulSoup,将会报错bs4包不支持

解决任何不支持的包的方法是这样的:

  1. 本地已经自动新建了一个文件名为scrapinghub.yml。打开这个文件,在project下面添加。
project:
requirements:
  file: requirements.txt

2. 在本项目根目录(即,scrapinghub.yml同级)创建文本文件requirements.txt

3. 打开requirements.txt,写入出问题的包的名字、版本,按照以下格式写。

beautifulsoup4==4.7.1

4. 要查看包的具体版本,在终端中输入pip show。例如。

pip show beautifulsoup4

5. 保存所有文件,再次在终端中推送项目。

shub deploy

这次应该可以成功了!

在云端运行爬虫:选择项目页面上的Run(运行)即可。

注意:

因内容长度关系,本文没有提及代码开头需要载入的python包。实际运行中如果没有载入相应的包,python会报错。

BeautifulSoup中为抓取网页内容所使用的标签也仅为示例,不同网站请使用浏览器的View Source和Inspect功能来查看具体标签。

bs4运行较慢,高级选择建议使用xpath或者scrapy selector来选取标签。

selenium速度也很慢,作为网站调试工具,会载入过多不相干的网页内容。

请保持良好的爬虫礼仪,尊重网站机器人条款、勿高速爬取造成服务器负担、爬取的内容勿做非法用途、请勿侵权。

学习之途漫漫,与君共勉!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值