目录
- Scrapy架构
- Scrapy爬虫能解决什么问题
- Scrapy爬虫注意事项
- Login问题
- xpath工具
- 保存数据到mysql
- 写在最后
1. Scrapy架构
具体介绍网页抓取过程请参考Scrapy
更多信息请参考Scapy官网
2. Scrapy爬虫能解决什么问题
相对于直接使用http请求库(如requests), 网页解析库(如lxml),Scrapy能够帮助我们专心与网页解析,可以并发的抓取网页,而不用去处理线程、进程以及异步请求等问题。
Scrapy究竟做了哪些事情:
- 根据web服务器与抓取程序的客户端主机压力,控制网页抓取速度,可配置(如AUTOTHROTTLE_ENABLED等)
- 可抓取网页的并发配置(如CONCURRENT_REQUESTS等)
- 抓取默认遵循网站的robots.txt, 可配置(ROBOTSTXT_OBEY)
- 保存session,自动处理cookie
- 能够避免重定向陷阱
- 失败重试,重试次数可配置
- 过滤重复请求
- 自动处理网页压缩问题(如gzip压缩)
- 自动处理字符编码
- 抓取的可输出到文档(如json, xml)或数据库(mysql, mongodb)
- 提供Http cache功能(如HTTPCACHE_ENABLED等)
- 提供log模块
- 等等
3. Scrapy爬虫注意事项
(1)USER_AGENT
由于网站的限制,如果抓取时没有配置USER_AGENT时,会不同服务端报错,如:
DEBUG: Crawled (403) <GET http://www.xxx.com/robots.txt> (referer: None)
DEBUG: Crawled (403) <GET http://www.xxx.com/users/{userid}> (referer: None)
INFO: Ignoring response <403 http://www.xxx.com/users/{userid}>: HTTP status code is not handled or not allowed
INFO: Closing spider (finished)
请配置settings.py中的USER_AGENT,或在DEFAULT_REQUEST_HEADERS中加入USER_AGENT配置
(2)DEFAULT_REQUEST_HEADERS
我们都知道网页请求需要加上请求头,不同的网站可能有不同的请求头,在抓取网页之前设置请求头,如:
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8',
'Accept-Language': 'en',
'authorization': 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20',
}
或在请求网页时加上HEADER参数
scrapy.Request('https://www.xxx.com',meta={'cookiejar':1}, headers=headers, callback=self.parse)]
4. Login问题
如果登陆网站没有验证码,怎可以通过CrawlSpider或者InitSpider取抓取,在登陆页有验证码时,现在还不知道怎么抓取。
另外就是登陆也会涉及到_xsrf问题,将_xsrf添加到登陆参数中即可。
5. xpath工具
chrome 提供了xpath插件,可以帮助我们调试xpath。
xpath插件
效果:
6. 保存数据到mysql
class JsMysqlPipeline(object):
def __init__(self):
self._mysql = None
def open_spider(self, spider):
self._mysql = pymysql.connect(host='localhost', user='root',
password='', db='crawler_js', charset='utf8')
def close_spider(self, spider):
self._mysql.close()
def process_item(self, item, spider):
insert_shops = "INSERT INTO `users` " \
"(`url_token`, `name`, `following_count`, `followers_count`," \
" `articles_count`, `words_count`, `like_count`)"
insert_value = "VALUES ({url_token!r}, {name!r}, {following_count}," \
"{followers_count}, {articles_count}, {words_count}, {like_count});"\
.format(**item)
ddl = "\n".join([insert_shops, insert_value])
with self._mysql.cursor() as cursor:
# Create a new record
cursor.execute(ddl)
# connection is not autocommit by default. So you must commit to save
# your changes.
self._mysql.commit()
return item
7. 写在最后
源码
关于登陆验证码问题,一直没有想到办法解决,欢迎一起讨论。