1, 安装:
pip3 install scrapy
scrapy依赖的包也会一并安装,不需要额外再安装什么东西了。
建议在virtualfish下安装,这样可以管理版本。
2, 新建项目:
scrapy startproject craigslist
会在当前目录为你创建一个craigslist project, craigslist是目录名称,也就是说是整个project的框架。目录结构如下:
├── scrapy.cfg
└── craigslist
├── __init__.py
├── items.py
├── pipelines.py
├── settings.py
└── spiders
└── __init__.py
这个目录里的spiders目录才是真的蜘蛛,一个项目可以包含多个蜘蛛。
进入spiders目录,新建一个spider。我们可以自己手动建一个文件,也可以让scrapy帮我创建。
若让scrapy帮我们创建,则先进入spiders目录:
scrapy genspider realestate newyork.craigslist.org/d/real-estate/search/rea
它会为我们自动创建一个名为 realestate.py的文件,这就是我们的一个蜘蛛。
3, 运行:
运行一个spider的方法:
scrapy crawl realestate
4, 调试
4.1, Scrapy Shell
使用 inspect_response 可以在代码里将scrapy shell 调出来,在执行到某行的时候,直接进入命令行进行调试。
官方调试文档:
https://docs.scrapy.org/en/latest/topics/debug.html
Parse Command
Scrapy Shell
Open in browser
Logging
5, GUI
可以使用 Scrapy-GUI 来可视化。
6, 工具组合
Selenium
(另外,除了selenium之外,google也出了一款用node.js写的控制浏览器的网页测试库 Puppeteer,可以替代selenium,但是现在它和scrapy结合使用的文档太少。只能用 js 开发, 只支持 Chrome headless。而webdriver 是一个大而全的解决方案,可以用 C#, Java, JS, Python,Ruby开发,支持 IE,FireFox, Safari,Chrome,andriod Chrome, 等等。同样是实现针对 Chrome的测试,webdriver 需要通过调用 chromedriver 提供的 Chrome Remote Debug Protocol, 再封装一层保持接口统一。puppeteer 则是直接和 chrome 建立 websocket 链接,通过 msg, 直接发送 Protocol 让 chrome 来执行对应的操作。如果不考虑兼容性,puppeteer 可以带来更好的性能(少了一层调用的原因),更多的功能,以及 Chrome 团队直接的支持)
headless chrome or headless firefox
BeautifulSoup
scrapy可以很好的抓取静态页面,静态页面可以不需要浏览器参与,但现在动态网站越来越多(即用js来生成页面及元素),因此需要浏览器来完成动态渲染,因此需要无头浏览器的参与。怎么判断页面是动态的还是静态的?
你可以浏览该页面的html源码,在这上面查找你需要的元素,如果不能找到,那么很可能该页面是通过js来动态渲染的。
你还可以通过浏览器来查看:
chrome浏览器如何断点调试异步加载的JS
在我们日常开发中,常常利用chrome强大的控制台Sources下面进行代码断点调试,但是通过$.getScript
等异步加载JS的方式在Sources里面就是找不到,那如何进行debug断点调试呢?下面来一起看看。
这是我们用Sources断点调试的实例图(点击浏览器调试界面的 sources):
当你用Chrome的Network查找异步加载的请求的时候,往往需要在一大堆请求中定位。一个个看过来往往很费时间。一个技巧可以让你快速定位。点击任意一个请求后,按住 Ctrl + F。这时候就会多出一个全局搜索框。然后通过搜索框搜索相关数据就能快速定位到请求了,比如输入 “下一页”等。
认证登陆:
有些页面需要登陆或认证才能访问,最简单的方法就是使用 webdriver,我们可以使用 Selenium 配合webdriver自动填充认证字段。
图形验证码Captcha:
Handling Redirects and Captchas
The Python Requests Library takes care of your HTTP redirects by following them and then returning to the final page. Scrapy also has a powerful way to handle redirects: you can set the redirect middleware to handle redirects.
If you are tired of handling redirect and captchas, you can also use Crawlera in your Scrapy project.
Simple text-based captchas can be solved by using OCR (optical character recognition); you can use pytesseract python library for solving captchas.
Solving captchas is considerable overhead in the scraping process, so if you want to get rid of this overhead, you can employ the help of APIs such as Anti Captcha and Death by Captcha.
Honeypot Traps
Some website developers put honeypot traps in the form of links which are not visible to the typical user on the browser. The easiest way to set the honeypot is by setting the CSS as display: none
. Since the web crawler script does not operate the way a human does, it can try to scrape the information from the link. As a result, the website detects the scraping and blocks the source IP address. 在某些页面加入不浏览器不显示的超级链接,让爬虫去爬,这样就能鉴别是不是爬虫在访问网页,然后禁用调当前ip。
This detection is not easy and requires a significant amount of programming work to accomplish correctly.
7,scrapy + Selenium + headless chrome
先安装:
pip3 install selenium
再安装chrome,然后再下载 chrome webdriver,在这里下载:
Quickstart:
from selenium import webdriver
DRIVER_PATH = '/path/to/chromedriver'
driver = webdriver.Chrome(executable_path=DRIVER_PATH)
driver.get('https://baidu.com')
这会启动一个headful 浏览器,与正常浏览器没有任何区别。
若要启动headless 浏览器,则:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
# 与 options.headless = True 作用相同
# chrome_options.add_argument("--headless")
#chrome_options.add_argument("--disable-extensions")
#chrome_options.add_argument("--disable-gpu")
#chrome_options.add_argument("--no-sandbox") # linux only
options.add_argument("--window-size=1920,1200")
driver = webdriver.Chrome(options=options, executable_path=DRIVER_PATH)
driver.get("https://www.nintendo.com/")
print(driver.page_source.encode("utf-8"))
# print(driver.page_source)
driver.quit()
8,增量式爬取
9,分布式爬虫
若运行单机爬虫,只在一台电脑上运行速度是有限的,所以后面我们要想提高抓取效率,需要用到分布式爬虫,在这里需要用到 Redis 来维护一个公共的爬取队列。
分布式爬虫有几个不同模式,会导致结构不一样,举个例子:
1、多台机器同时爬取目标url并且同时从url中抽取数据,N台机器做一模一样的事,通过redis来调度、中转,也就是说它根本没有主机从机之分。
2、总共N+M台机器,其中N台机器负责爬取目标URL,另外M台机器负责容url中抽取数据,N和M做的事不一样,他们也是通过redis来进行调度和中转,它有主机从机之分。
① request之前是放在内存的,现在两台服务器就需要对队列进行集中管理。
② 去重也要进行集中管理