场景介绍:利用scrapy框架,搭配selenium对数据进行爬取
获取页面信息的方式:
- xpath:response.xpath
- json : jsonxpath.jsonpath(response,“jsonpath的表达式”) 注意结果为list
- 正则
- css (个人目前不常用)
应用一:scrapy可以直接获取信息
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demoSpider'
search='查询信息'
allowed_domains = ['网址范围']
start_urls=["具体请求的网址信息"]
# 默认的scrapy的处理结果的回调函数,可以自己编写,在后面的几个例子会进行展示
def parse(self, response):
print(response.headers)
print(response.text)
2.自定义回调函数和请求信息
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demoSpider'
search='查询信息'
allowed_domains = ['网址范围']
start_urls=["具体请求的网址信息"]
def start_requests(self):
yield scrapy.Request(url=url,
method="请求方式-scrapy默认get,post好像只能以表单的形式发送",
headers="头部信息,需要dict格式",
body="请求体,适用于playQuery",
meta={"request_obj": "可携带参数传递给回调函数来处理"},
callback=self.handle_datas)
# 此例子中这个parse将不会被执行
def parse(self, response):
print(response.headers)
print(response.text)
# 回调的处理器
def parse(self, response):
print("真正被回调的方法")
print(response.meta["request_obj"]) # 可携带参数传递给回调函数来处理
print(response.headers)
print(response.text)
应用二:scrapy+selenium实现动态加载页面的爬取
scrapy直接抓取的页面为原生页面,对于由js等加载进入的数据无法抓取到数据,特别是在当下这个前端的vue等框架都是使用js进行开发的,很多数据更是使用js不断生成的
# 1. 编写selenium中间件
class SeleniumMiddleWares(object):
def process_request(self, request, spider):
url = request.url
# 根据条件判断是否使用,若是不适用selenium则直接返回None
if "判断条件":
return None
# 设置请求头
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = "应对反爬UA检测"
options = webdriver.ChromeOptions()
# 忽略ssl错误
options.add_argument("--ignore-certificate-errors")
options.add_argument('--ignore-ssl-errors')
# 不显示界面
# options.add_argument("--headless")
# 开启无痕模式
options.add_argument('--incognito')
driver = webdriver.Chrome(executable_path="chromedriver路径,可通过配置环境信息省略此步",options=options, desired_capabilities=dcap)
driver.get(url)
# 获取页面源
data = driver.page_source
driver.close()
driver.quit()
res = HtmlResponse(url=url, body=data, encoding='utf-8', request=request)
return res
# 2. 在setting中开启selenium
DOWNLOADER_MIDDLEWARES = {
# 遇到404是不是很闹心,哈哈,这里根据自身情况设置,scrapy在请求是相当于一条线值越大,越在后期执行,例如 1先执行,2再执行,pipline也是如此
'BrandTable.middlewares.SeleniumMiddleWares': 404,
}
应用三:一个爬虫爬取多个网站信息
关于这个问题,可以参考在start_requests中循环遍历来发起多个请求,
也可以发送不同的请求回调不同的处理方法
应用四:scrpay+selenium爬取多个网站时,部分网站不开启selenium
实际上就是在selenium中进行判断返回,return None 就是不执行selenium,
否则根据指定情况返回结果,详细代码参考应用二
应用五:对接口返回的不完整代码使用xpath的数据截取
对于部分网站在修改页面数据时请求返回的是部分代码,通过这部分代码进行页面构建的,但是我们为了提高效率,又不想过多的使用selenium,所以需要对返回结果进行处理提炼,正则有时匹配难度较高,所以我们使用xpath鞥方便
from lxml import etree
res = etree.HTML(response.text["data"])
res=res.xpath("正常的xpath字符串")
print(res)
from bs4 import BeautifulSoup
res = BeautifulSoup(response.text,"html5lib")
res=etree.HTML(res.prettify())
res.xpath("正常的xpath字符串")
应用六:不能对同一请求发送连续的请求
关于这个问题,是由于scrapy的问题,scrapy对同一请求进行了过滤,解决方案就是在发起请求时设置取消过滤
# 例如
yield scrapy.Request(url=url,dont_filter=True)
# 补充 scrapy 对数据导入到下一步操作均是使用yield,包含parse将数据处理之后给pipline
应用七:传递form数据的请求
表单的形式传递参数是常用的
yield FormRequest(url=obj["urls"][0]["url"],encoding="utf-8",formdata={"字段":"值"},)
备注:
小白一枚,以上是本人近期对scrapy进行使用时学习到的,有什么不足的欢迎大家指教(本人是搞java的,大家可以一起进步呢)