requestium 0.4.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {requestium-0.4.0 → requestium-0.6.0}/PKG-INFO +116 -78
- requestium-0.4.0/requestium.egg-info/PKG-INFO → requestium-0.6.0/README.md +88 -84
- requestium-0.6.0/pyproject.toml +150 -0
- {requestium-0.4.0 → requestium-0.6.0}/requestium/__init__.py +2 -1
- requestium-0.6.0/requestium/requestium.py +6 -0
- requestium-0.6.0/requestium/requestium_mixin.py +255 -0
- requestium-0.6.0/requestium/requestium_response.py +34 -0
- requestium-0.6.0/requestium/requestium_session.py +234 -0
- requestium-0.4.0/README.md → requestium-0.6.0/requestium.egg-info/PKG-INFO +122 -67
- requestium-0.6.0/requestium.egg-info/SOURCES.txt +23 -0
- requestium-0.6.0/requestium.egg-info/requires.txt +4 -0
- requestium-0.6.0/tests/test_add_cookie.py +124 -0
- requestium-0.6.0/tests/test_cookies.py +144 -0
- requestium-0.6.0/tests/test_driver_parsing.py +48 -0
- requestium-0.6.0/tests/test_ensure_element.py +196 -0
- requestium-0.6.0/tests/test_mixin.py +91 -0
- requestium-0.6.0/tests/test_proxy.py +53 -0
- requestium-0.6.0/tests/test_remote_driver.py +98 -0
- requestium-0.6.0/tests/test_response_parsing.py +107 -0
- requestium-0.6.0/tests/test_session.py +173 -0
- requestium-0.6.0/tests/test_user_agent.py +81 -0
- requestium-0.4.0/.travis.yml +0 -38
- requestium-0.4.0/MANIFEST.in +0 -5
- requestium-0.4.0/pyproject.toml +0 -20
- requestium-0.4.0/requestium/requestium.py +0 -412
- requestium-0.4.0/requestium.egg-info/SOURCES.txt +0 -15
- requestium-0.4.0/requestium.egg-info/not-zip-safe +0 -1
- requestium-0.4.0/requestium.egg-info/requires.txt +0 -4
- requestium-0.4.0/setup.py +0 -38
- requestium-0.4.0/tox.ini +0 -14
- {requestium-0.4.0 → requestium-0.6.0}/LICENSE +0 -0
- {requestium-0.4.0 → requestium-0.6.0}/requestium.egg-info/dependency_links.txt +0 -0
- {requestium-0.4.0 → requestium-0.6.0}/requestium.egg-info/top_level.txt +0 -0
- {requestium-0.4.0 → requestium-0.6.0}/setup.cfg +0 -0
|
@@ -1,35 +1,56 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: requestium
|
|
3
|
-
Version: 0.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Author-email: Joaquin Alori <joaquin@tryolabs.com>
|
|
5
|
+
Maintainer-email: Judson Neer <judson.neer@gmail.com>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: source, https://github.com/tryolabs/requestium
|
|
8
|
+
Project-URL: download, https://pypi.org/project/requestium/#files
|
|
9
|
+
Project-URL: issues, https://github.com/tryolabs/requestium/issues
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
17
|
Classifier: Natural Language :: English
|
|
12
|
-
Classifier:
|
|
13
|
-
Classifier:
|
|
14
|
-
Classifier:
|
|
18
|
+
Classifier: Operating System :: MacOS
|
|
19
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
20
|
+
Classifier: Operating System :: POSIX
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Environment :: Web Environment
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Classifier: Topic :: Software Development :: Testing
|
|
26
|
+
Requires-Python: >=3.10
|
|
15
27
|
Description-Content-Type: text/markdown
|
|
16
28
|
License-File: LICENSE
|
|
29
|
+
Requires-Dist: parsel>=1.8
|
|
30
|
+
Requires-Dist: requests>=2.27
|
|
31
|
+
Requires-Dist: selenium>=4.32
|
|
32
|
+
Requires-Dist: tldextract>=5.3
|
|
33
|
+
Dynamic: license-file
|
|
17
34
|
|
|
18
35
|

|
|
19
36
|
========
|
|
20
37
|
|
|
21
|
-
[](https://travis-ci.org/tryolabs/requestium)
|
|
22
38
|
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
39
|
+
[](https://pypi.org/project/requestium/)
|
|
40
|
+
[](https://pypi.org/project/requestium/)
|
|
41
|
+
[](https://htmlpreview.github.io/?https://github.com/tryolabs/requestium/blob/python-coverage-comment-action-data/htmlcov/index.html)
|
|
42
|
+
[](https://github.com/tryolabs/requestium/actions/workflows/python.yml)
|
|
23
43
|
|
|
24
|
-
Requestium is a Python library that merges the power of [Requests](https://github.com/requests/requests), [Selenium](https://github.com/SeleniumHQ/selenium), and [Parsel](https://github.com/scrapy/parsel) into a single integrated tool for
|
|
44
|
+
Requestium is a Python library that merges the power of [Requests](https://github.com/requests/requests), [Selenium](https://github.com/SeleniumHQ/selenium), and [Parsel](https://github.com/scrapy/parsel) into a single integrated tool for automating web actions.
|
|
25
45
|
|
|
26
46
|
The library was created for writing web automation scripts that are written using mostly Requests but that are able to seamlessly switch to Selenium for the JavaScript heavy parts of the website, while maintaining the session.
|
|
27
47
|
|
|
28
48
|
Requestium adds independent improvements to both Requests and Selenium, and every new feature is lazily evaluated, so its useful even if writing scripts that use only Requests or Selenium.
|
|
29
49
|
|
|
30
|
-
Read more about the motivation behind creating this library in this [
|
|
50
|
+
Read more about the motivation behind creating this library in this [blog post](https://tryolabs.com/blog/2017/11/22/requestium-integration-layer-requests-selenium-web-automation/).
|
|
31
51
|
|
|
32
52
|
## Features
|
|
53
|
+
|
|
33
54
|
- Enables switching between a Requests' Session and a Selenium webdriver while maintaining the current web session.
|
|
34
55
|
- Integrates Parsel's parser into the library, making xpath, css, and regex much cleaner to write.
|
|
35
56
|
- Improves Selenium's handling of dynamically loading elements.
|
|
@@ -38,27 +59,29 @@ Read more about the motivation behind creating this library in this [blopost](ht
|
|
|
38
59
|
- Supports Chromedriver natively plus adding a custom webdriver.
|
|
39
60
|
|
|
40
61
|
## Installation
|
|
62
|
+
|
|
41
63
|
```bash
|
|
42
64
|
pip install requestium
|
|
43
65
|
```
|
|
44
66
|
|
|
45
|
-
|
|
67
|
+
Selenium 4.6+ includes Selenium Manager, which downloads the matching driver (such as Chromedriver) automatically, so you don't need to install one yourself. If you prefer to manage the driver yourself, download it and pass its location with the `webdriver_path` argument.
|
|
46
68
|
|
|
47
69
|
## Usage
|
|
48
70
|
First create a session as you would do on Requests, and optionally add arguments for the web-driver if you plan to use one.
|
|
71
|
+
|
|
49
72
|
```python
|
|
50
73
|
from requestium import Session, Keys
|
|
51
74
|
|
|
52
|
-
options = {
|
|
53
|
-
s = Session(webdriver_path=
|
|
75
|
+
options = {"arguments": ["headless"]}
|
|
76
|
+
s = Session(webdriver_path="./chromedriver", default_timeout=15, webdriver_options=options)
|
|
54
77
|
```
|
|
55
78
|
|
|
56
|
-
Since headless mode is common, there's a shortcut for it by
|
|
79
|
+
Since headless mode is common, there's a shortcut for it by specifying `headless=True`.
|
|
57
80
|
|
|
58
81
|
```python
|
|
59
82
|
from requestium import Session, Keys
|
|
60
83
|
|
|
61
|
-
s = Session(webdriver_path=
|
|
84
|
+
s = Session(webdriver_path="./chromedriver", headless=True)
|
|
62
85
|
```
|
|
63
86
|
|
|
64
87
|
You can also create a Selenium webdriver outside Requestium and have it use that instead:
|
|
@@ -72,7 +95,19 @@ firefox_driver = webdriver.Firefox()
|
|
|
72
95
|
s = Session(driver=firefox_driver)
|
|
73
96
|
```
|
|
74
97
|
|
|
75
|
-
|
|
98
|
+
A remote webdriver works too, with all the `ensure_*` and xpath/css/re helpers:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from selenium import webdriver
|
|
102
|
+
from requestium import Session
|
|
103
|
+
|
|
104
|
+
options = webdriver.ChromeOptions()
|
|
105
|
+
remote_driver = webdriver.Remote(command_executor="http://localhost:4444/wd/hub", options=options)
|
|
106
|
+
|
|
107
|
+
s = Session(driver=remote_driver)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You can also pass an instance of a 3rd party webdriver class, such as Chrome from [Selenium-Wire](https://github.com/wkeeling/selenium-wire), which lets you get the XHR requests of a web page. When `driver` is given, `webdriver_path` is ignored:
|
|
76
111
|
|
|
77
112
|
```python
|
|
78
113
|
from seleniumwire import webdriver
|
|
@@ -80,41 +115,45 @@ from requestium import Session, Keys
|
|
|
80
115
|
|
|
81
116
|
seleniumwire_driver = webdriver.Chrome()
|
|
82
117
|
|
|
83
|
-
s = Session(
|
|
84
|
-
|
|
118
|
+
s = Session(driver=seleniumwire_driver)
|
|
85
119
|
```
|
|
86
120
|
|
|
87
121
|
You don't need to parse the response, it is done automatically when calling xpath, css or re.
|
|
122
|
+
|
|
88
123
|
```python
|
|
89
|
-
title = s.get(
|
|
124
|
+
title = s.get("http://samplesite.com").xpath("//title/text()").extract_first(default="Default Title")
|
|
90
125
|
```
|
|
91
126
|
|
|
92
127
|
Regex require less boilerplate when compared to Python's standard `re` module.
|
|
128
|
+
|
|
93
129
|
```python
|
|
94
|
-
response = s.get(
|
|
130
|
+
response = s.get("http://samplesite.com/sample_path")
|
|
95
131
|
|
|
96
132
|
# Extracts the first match
|
|
97
|
-
identifier = response.re_first(r
|
|
133
|
+
identifier = response.re_first(r"ID_\d\w\d", default="ID_1A1")
|
|
98
134
|
|
|
99
135
|
# Extracts all matches as a list
|
|
100
|
-
users = response.re(r
|
|
136
|
+
users = response.re(r"user_\d\d\d")
|
|
101
137
|
```
|
|
102
138
|
|
|
103
|
-
The Session object is just a regular Requests's session object, so you can use all of its methods.
|
|
139
|
+
The Session object is just a regular Requests's session object, so you can use all of its methods. Responses from all HTTP verbs (get, post, put, patch, delete, head, options) have the xpath, css, and re helpers.
|
|
140
|
+
|
|
104
141
|
```python
|
|
105
|
-
s.post(
|
|
106
|
-
s.proxies.update({
|
|
142
|
+
s.post("http://www.samplesite.com/sample", data={"field1": "data1"})
|
|
143
|
+
s.proxies.update({"http": "http://10.11.4.254:3128", "https": "https://10.11.4.252:3128"})
|
|
107
144
|
```
|
|
108
145
|
|
|
109
146
|
And you can switch to using the Selenium webdriver to run any js code.
|
|
147
|
+
|
|
110
148
|
```python
|
|
111
149
|
s.transfer_session_cookies_to_driver() # You can maintain the session if needed
|
|
112
|
-
s.driver.get(
|
|
150
|
+
s.driver.get("http://www.samplesite.com/sample/process")
|
|
113
151
|
```
|
|
114
152
|
|
|
115
153
|
The driver object is a Selenium webdriver object, so you can use any of the normal selenium methods plus new methods added by Requestium.
|
|
154
|
+
|
|
116
155
|
```python
|
|
117
|
-
s.driver.find_element("xpath", "//input[@class='user_name']").send_keys(
|
|
156
|
+
s.driver.find_element("xpath", "//input[@class='user_name']").send_keys("James Bond", Keys.ENTER)
|
|
118
157
|
|
|
119
158
|
# New methods which wait for element to load instead of failing, useful for single page web apps
|
|
120
159
|
s.driver.ensure_element("xpath", "//div[@attribute='button']").click()
|
|
@@ -122,15 +161,26 @@ s.driver.ensure_element_by_xpath("//div[@attribute='button']").click()
|
|
|
122
161
|
```
|
|
123
162
|
|
|
124
163
|
Requestium also adds xpath, css, and re methods to the Selenium driver object.
|
|
164
|
+
|
|
125
165
|
```python
|
|
126
|
-
if s.driver.re(r
|
|
127
|
-
print(
|
|
166
|
+
if s.driver.re(r"ID_\d\w\d some_pattern"):
|
|
167
|
+
print("Found it!")
|
|
128
168
|
```
|
|
129
169
|
|
|
130
170
|
And finally you can switch back to using Requests.
|
|
171
|
+
|
|
131
172
|
```python
|
|
132
173
|
s.transfer_driver_cookies_to_session()
|
|
133
|
-
s.post(
|
|
174
|
+
s.post("http://www.samplesite.com/sample2", data={"key1": "value1"})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
When you are done, close the session. This quits the webdriver if one was started, including a driver you passed in. It also works as a context manager.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
s.close()
|
|
181
|
+
|
|
182
|
+
with Session(headless=True) as s:
|
|
183
|
+
s.driver.get("http://www.samplesite.com")
|
|
134
184
|
```
|
|
135
185
|
|
|
136
186
|
## Selenium workarounds
|
|
@@ -140,6 +190,7 @@ Requestium adds several 'ensure' methods to the driver object, as Selenium is kn
|
|
|
140
190
|
The `ensure_element` and `ensure_element_by_` methods wait for the element to be loaded in the browser and returns it as soon as it loads. They're named after Selenium's `find_element` and `find_element_by_` methods (which immediately raise an exception if they can't find the element).
|
|
141
191
|
|
|
142
192
|
Requestium can wait for an element to be in any of the following states:
|
|
193
|
+
|
|
143
194
|
- present (default)
|
|
144
195
|
- clickable
|
|
145
196
|
- visible
|
|
@@ -150,7 +201,7 @@ These methods are very useful for single page web apps where the site is dynamic
|
|
|
150
201
|
Elements you get using these methods have the new `ensure_click` method which makes the click less prone to failure. This helps with getting through a lot of the problems with Selenium clicking.
|
|
151
202
|
|
|
152
203
|
```python
|
|
153
|
-
s.driver.ensure_element("xpath", "//li[@class='b1']", state=
|
|
204
|
+
s.driver.ensure_element("xpath", "//li[@class='b1']", state="clickable", timeout=5).ensure_click()
|
|
154
205
|
|
|
155
206
|
# === We also added these methods named in accordance to Selenium's api design ===
|
|
156
207
|
# ensure_element_by_id
|
|
@@ -164,61 +215,57 @@ s.driver.ensure_element("xpath", "//li[@class='b1']", state='clickable', timeout
|
|
|
164
215
|
```
|
|
165
216
|
|
|
166
217
|
### Add cookie
|
|
167
|
-
The `ensure_add_cookie` method makes adding cookies much more robust. Selenium needs the browser to be at the cookie's domain before being able to add the cookie, this method offers several workarounds for this. If the browser is not in the cookies domain, it GETs the domain before adding the cookie. It also allows you to override the domain before adding it, and avoid making this GET. The domain can be overridden to `''`, this sets the cookie's domain to whatever domain the driver is currently in.
|
|
218
|
+
The `ensure_add_cookie` method makes adding cookies much more robust. Selenium needs the browser to be at the cookie's domain before being able to add the cookie, this method offers several workarounds for this. If the browser is not in the cookies domain, it GETs the domain before adding the cookie, over https if the cookie is `secure` and over http otherwise. It also allows you to override the domain before adding it, and avoid making this GET. The domain can be overridden to `''`, this sets the cookie's domain to whatever domain the driver is currently in.
|
|
168
219
|
|
|
169
220
|
If it can't add the cookie it tries to add it with a less restrictive domain (Eg.: home.site.com -> site.com) before failing.
|
|
170
221
|
|
|
171
222
|
```python
|
|
172
|
-
cookie = {"domain": "www.site.com",
|
|
173
|
-
|
|
174
|
-
"value": "sd2451dgd13",
|
|
175
|
-
"expiry": 1516824855.759154,
|
|
176
|
-
"path": "/",
|
|
177
|
-
"httpOnly": true,
|
|
178
|
-
"name": "sessionid"}
|
|
179
|
-
s.driver.ensure_add_cookie(cookie, override_domain='')
|
|
223
|
+
cookie = {"domain": "www.site.com", "secure": False, "value": "sd2451dgd13", "expiry": 1516824855.759154, "path": "/", "httpOnly": True, "name": "sessionid"}
|
|
224
|
+
s.driver.ensure_add_cookie(cookie, override_domain="")
|
|
180
225
|
```
|
|
181
226
|
|
|
182
227
|
## Considerations
|
|
183
228
|
New features are lazily evaluated, meaning:
|
|
229
|
+
|
|
184
230
|
- The Selenium webdriver process is only started if you call the driver object. So if you don't need to use the webdriver, you could use the library with no overhead. Very useful if you just want to use the library for its integration with Parsel.
|
|
185
231
|
- Parsing of the responses is only done if you call the `xpath`, `css`, or `re` methods of the response. So again there is no overhead if you don't need to use this feature.
|
|
186
232
|
|
|
187
233
|
A byproduct of this is that the Selenium webdriver could be used just as a tool to ease in the development of regular Requests code: You can start writing your script using just the Requests' session, and at the last step of the script (the one you are currently working on) transfer the session to the Chrome webdriver. This way, a Chrome process starts in your machine, and acts as a real time "visor" for the last step of your code. You can see in what state your session is currently in, inspect it with Chrome's excellent inspect tools, and decide what's the next step your session object should take. Very useful to try code in an IPython interpreter and see how the site reacts in real time.
|
|
188
234
|
|
|
189
235
|
When `transfer_driver_cookies_to_session` is called, Requestium automatically updates your Requests session user-agent to match that of the browser used in Selenium. This doesn't happen when running Requests without having switched from a Selenium session first though. So if you just want to run Requests but want it to use your browser's user agent instead of the default one (which sites love to block), just run:
|
|
236
|
+
|
|
190
237
|
```python
|
|
191
238
|
s.copy_user_agent_from_driver()
|
|
192
239
|
```
|
|
193
240
|
Take into account that doing this will launch a browser process.
|
|
194
241
|
|
|
195
|
-
|
|
242
|
+
When Requestium launches its own Chrome, it carries over the session's `proxies` (as `--proxy-server`) and a custom `User-Agent` header, as long as they are set before the driver is first used. Proxies with credentials aren't supported by Chrome flags and are skipped with a warning. Other headers are not synced. This doesn't apply to a driver you pass in yourself.
|
|
196
243
|
|
|
197
244
|
## Comparison with Requests + Selenium + lxml
|
|
198
245
|
A silly working example of a script that runs on Reddit. We'll then show how it compares to using Requests + Selenium + lxml instead of Requestium.
|
|
199
246
|
|
|
200
247
|
### Using Requestium
|
|
248
|
+
|
|
201
249
|
```python
|
|
202
250
|
from requestium import Session, Keys
|
|
203
251
|
|
|
204
252
|
# If you want requestium to type your username in the browser for you, write it in here:
|
|
205
|
-
reddit_user_name =
|
|
253
|
+
reddit_user_name = ""
|
|
206
254
|
|
|
207
|
-
s = Session(
|
|
208
|
-
s.driver.get(
|
|
255
|
+
s = Session(default_timeout=15)
|
|
256
|
+
s.driver.get("http://reddit.com")
|
|
209
257
|
s.driver.find_element("xpath", "//a[@href='https://www.reddit.com/login']").click()
|
|
210
258
|
|
|
211
|
-
print(
|
|
212
|
-
s.driver.ensure_element("class name", "desktop-onboarding-sign-up__form-toggler",
|
|
213
|
-
state='visible').click()
|
|
259
|
+
print("Waiting for elements to load...")
|
|
260
|
+
s.driver.ensure_element("class name", "desktop-onboarding-sign-up__form-toggler", state="visible").click()
|
|
214
261
|
|
|
215
262
|
if reddit_user_name:
|
|
216
|
-
s.driver.ensure_element(
|
|
217
|
-
s.driver.ensure_element(
|
|
218
|
-
print(
|
|
263
|
+
s.driver.ensure_element("id", "user_login").send_keys(reddit_user_name)
|
|
264
|
+
s.driver.ensure_element("id", "passwd_login").send_keys(Keys.BACKSPACE)
|
|
265
|
+
print("Please log-in in the chrome browser")
|
|
219
266
|
|
|
220
|
-
s.driver.ensure_element("class name", "desktop-onboarding__title", timeout=60, state=
|
|
221
|
-
print(
|
|
267
|
+
s.driver.ensure_element("class name", "desktop-onboarding__title", timeout=60, state="invisible")
|
|
268
|
+
print("Thanks!")
|
|
222
269
|
|
|
223
270
|
if not reddit_user_name:
|
|
224
271
|
reddit_user_name = s.driver.xpath("//span[@class='user']//text()").extract_first()
|
|
@@ -248,34 +295,26 @@ from selenium.webdriver.support.ui import WebDriverWait
|
|
|
248
295
|
from selenium.webdriver.support import expected_conditions as EC
|
|
249
296
|
|
|
250
297
|
# If you want requestium to type your username in the browser for you, write it in here:
|
|
251
|
-
reddit_user_name =
|
|
298
|
+
reddit_user_name = ""
|
|
252
299
|
|
|
253
|
-
driver = webdriver.Chrome(
|
|
254
|
-
driver.get(
|
|
300
|
+
driver = webdriver.Chrome()
|
|
301
|
+
driver.get("http://reddit.com")
|
|
255
302
|
driver.find_element("xpath", "//a[@href='https://www.reddit.com/login']").click()
|
|
256
303
|
|
|
257
|
-
print(
|
|
258
|
-
WebDriverWait(driver, 15).until(
|
|
259
|
-
EC.visibility_of_element_located((By.CLASS_NAME, "desktop-onboarding-sign-up__form-toggler"))
|
|
260
|
-
).click()
|
|
304
|
+
print("Waiting for elements to load...")
|
|
305
|
+
WebDriverWait(driver, 15).until(EC.visibility_of_element_located((By.CLASS_NAME, "desktop-onboarding-sign-up__form-toggler"))).click()
|
|
261
306
|
|
|
262
307
|
if reddit_user_name:
|
|
263
|
-
WebDriverWait(driver, 15).until(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
driver.find_element('id', 'passwd_login').send_keys(Keys.BACKSPACE)
|
|
267
|
-
print('Please log-in in the chrome browser')
|
|
308
|
+
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.ID, "user_login"))).send_keys(reddit_user_name)
|
|
309
|
+
driver.find_element("id", "passwd_login").send_keys(Keys.BACKSPACE)
|
|
310
|
+
print("Please log-in in the chrome browser")
|
|
268
311
|
|
|
269
312
|
try:
|
|
270
|
-
WebDriverWait(driver, 3).until(
|
|
271
|
-
EC.presence_of_element_located((By.CLASS_NAME, "desktop-onboarding__title"))
|
|
272
|
-
)
|
|
313
|
+
WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.CLASS_NAME, "desktop-onboarding__title")))
|
|
273
314
|
except TimeoutException:
|
|
274
315
|
pass
|
|
275
|
-
WebDriverWait(driver, 60).until(
|
|
276
|
-
|
|
277
|
-
)
|
|
278
|
-
print('Thanks!')
|
|
316
|
+
WebDriverWait(driver, 60).until(EC.invisibility_of_element_located((By.CLASS_NAME, "desktop-onboarding__title")))
|
|
317
|
+
print("Thanks!")
|
|
279
318
|
|
|
280
319
|
if not reddit_user_name:
|
|
281
320
|
tree = etree.HTML(driver.page_source)
|
|
@@ -290,11 +329,10 @@ if reddit_user_name:
|
|
|
290
329
|
selenium_user_agent = driver.execute_script("return navigator.userAgent;")
|
|
291
330
|
s.headers.update({"user-agent": selenium_user_agent})
|
|
292
331
|
for cookie in driver.get_cookies():
|
|
293
|
-
s.cookies.set(cookie[
|
|
332
|
+
s.cookies.set(cookie["name"], cookie["value"], domain=cookie["domain"])
|
|
294
333
|
response = s.get("https://www.reddit.com/user/{}/".format(reddit_user_name))
|
|
295
334
|
try:
|
|
296
|
-
cmnt_karma = etree.HTML(response.content).xpath(
|
|
297
|
-
"//span[@class='karma comment-karma']//text()")[0]
|
|
335
|
+
cmnt_karma = etree.HTML(response.content).xpath("//span[@class='karma comment-karma']//text()")[0]
|
|
298
336
|
except IndexError:
|
|
299
337
|
cmnt_karma = None
|
|
300
338
|
match = re.search(r"(\d+) gildings given out", str(response.content))
|